
#include "MCone.h"


MCone::MCone(float ar, float ah, int ars, int avs, int acn, float aox , float aoy ,float aoz )
{
	name = "Cone";
	verts = NULL;
	normal = NULL;
	bNormal = false;
	updateCone(ar,ah,ars,avs,acn,aox,aoy,aoz);
}


MCone::~MCone(void)
{
	if(verts) {
		for(int i = 0; i<rs; i++) {
			delete []verts[i];
		}
		delete []verts;
	}
	if(normal) {
		for(int i = 0; i<rs; i++) {
			delete normal[i];
		}
		delete []normal;
	}
}

void MCone::drawShape() {
	if(!verts) 
		return;
	MVertex top(0,r,0), buttom(0,-r,0);

}

MCone *MCone::makeCone(float ar, float ah, int ars, int avs, int acn, float aox, float aoy,float aoz) {
	if(ar<=0  || ah <=0 || ars < 1 || avs < 3 || acn < 1) {//at least 2 radial stacks and 3 vertical slice
		return NULL;
	}
	return new MCone(ar, ah,ars,avs,acn,aox,aoy,aoz);
}

void MCone::updateCone(float ar, float ah, int ars, int avs, int acn, float aox, float aoy,float aoz) {
	if(ar<=0  || ah <=0 || ars < 1 || avs < 3 || acn < 1) {//at least 2 radial stacks and 3 vertical slice
		return;
	}
	//delete old array
	if(verts) {
		for(int i = 0; i<rs; i++) {
			delete []verts[i];
		}
		delete []verts;
	}
	if(normal) {
		for(int i = 0; i<rs; i++) {
			delete normal[i];
		}
		delete []normal;
	}
	ox = aox;
	oy = aoy;
	oz = aoz;
	r = ar;
	h = ah;
	rs = ars;
	vs = avs;
	cn = acn;
	step = 1;
	//create array
	verts = new MVertex*[rs];
	normal = new MVertex*[rs];
	int i, j;
	for(i = 0; i<rs; i++) {
		verts[i] = new MVertex[vs];
		normal[i] = new MVertex[vs];
	}
	//populate data
	MVertex p1(0,h,0);
	for(i=0; i<rs; i++) {
		p1 = p1.translate(0,-h/rs,0);
		float newr = (float)(i+1)/(float)rs*r;
		verts[i][0] = p1.translate(newr,0,0);
		for(j=1; j<vs; j++) {
			verts[i][j] = verts[i][j-1].rotateY(2*PI/vs);
		}
	}

	for(i=0; i<rs; i++) {
		for(j=0; j<vs; j++) {
			MVertex top = (i==0?MVertex(0,h,0):verts[i-1][j]);
			MVertex bottom = (i==(rs-1)?verts[i][j]:verts[i+1][j]);
			MVertex left = (j==0?verts[i][vs-1]:verts[i][j-1]);
			MVertex right = (j==(vs-1)?verts[i][0]:verts[i][j+1]);
			calculateNormal(&normal[i][j],verts[i][j],top,bottom,left,right);
		}
	}
}

/*func is a function to draw triangles*/
void MCone::drawCone(void(*func)(const MVertex &p1,  const MVertex &p2, const MVertex &p3, int ic),
	void(*drawline)(const MVertex &p1,  const MVertex &p2,int ic)) {
	static const int icolor = 2;
	if(!func) {	//return function
		return;
	}
	int i, j;
	MVertex top(0,h,0);
	for(j=0; j<vs; j++) {
		func(top,verts[0][j],verts[0][(j==vs-1?0:j+1)],icolor);
	}
	for(i=0; i<rs-1; i++) {
		for(j=0; j<vs; j++) {
			int nextj = ((j==vs-1)?0:j+1);
			func(verts[i][j],verts[i+1][j],verts[i+1][nextj], icolor);
			func(verts[i+1][nextj],verts[i][nextj], verts[i][j],icolor);
		}
	}

	if(bNormal && drawline) {
		for(i=0; i<rs; i++) {
			for(j=0; j<vs; j++) {
				drawline(verts[i][j],verts[i][j]+normal[i][j]*NORMALEN,1);
			}
		}
	}
	if(step < vs) {
		step++;
	}
}

/*
void MCone::resetStep() {
	step = 1;
}

bool MCone::isComplete() const {
	return step == vs;
}
*/
void MCone::incrementSlice() {
	if(vs < 50) {
		this->updateCone(r,h,rs,vs+1,cn,ox,oy,oz);
	}
}

void MCone::decrementSlice() {
	if(vs > 3) {
		this->updateCone(r,h,rs,vs-1,cn,ox,oy,oz);
	}
}

void MCone::incrementStack() {
	if(rs < 50) {
		this->updateCone(r,h,rs+1,vs,cn,ox,oy,oz);
	}
}

void MCone::decrementStack() {
	if(rs > 1) {
		this->updateCone(r,h,rs-1,vs,cn,ox,oy,oz);
	}
}
